<template>
    <el-container style="padding: 20px; max-width: 800px; margin: auto;">
        <div class="container">
            <div v-for="(item, index) in boxes" :key="item.id" class="box" draggable="true"
                @dragstart="onDragStart($event, index)" @dragover.prevent @drop="onDrop($event, index)">
                <div class="box-header">
                    <el-button icon="el-icon-rank" circle size="mini" class="drag-handle" @mousedown.stop>拖拽</el-button>
                    <el-button icon="el-icon-delete" circle size="mini" class="delete-btn"
                        @click.stop="deleteBox(index)">删除</el-button>
                </div>
                <div class="box-content">
                    {{ item.content }}
                </div>
            </div>
        </div>
    </el-container>
</template>

<script lang="ts" setup>
import { ref } from 'vue'

interface Box {
    id: number
    content: string
}

const boxes = ref<Box[]>([
    { id: 1, content: '盒子 1' },
    { id: 2, content: '盒子 2' },
    { id: 3, content: '盒子 3' },
    { id: 4, content: '盒子 4' }
])

let dragIndex = -1

const onDragStart = (event: DragEvent, index: number) => {
    dragIndex = index
    // 设置拖拽数据，必须设置，否则拖拽无效
    event.dataTransfer?.setData('text/plain', String(index))
    // 设置拖拽效果
    event.dataTransfer!.effectAllowed = 'move'
}

const onDrop = (event: DragEvent, dropIndex: number) => {
    event.preventDefault()
    if (dragIndex === -1 || dragIndex === dropIndex) return

    const draggedItem = boxes.value[dragIndex]
    boxes.value.splice(dragIndex, 1) // 移除拖拽项
    boxes.value.splice(dropIndex, 0, draggedItem) // 插入到目标位置

    dragIndex = -1
}

const deleteBox = (index: number) => {
    boxes.value.splice(index, 1)
}
</script>

<style scoped>
.container {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

.box {
    position: relative;
    width: 600px;
    height: 300px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    background-color: #f5f7fa;
    box-sizing: border-box;
    padding: 10px;
    user-select: none;
}

.box-header {
    position: absolute;
    top: 8px;
    right: 8px;
    display: flex;
    gap: 8px;
    z-index: 10;
}

.drag-handle {
    cursor: grab;
}

.drag-handle:active {
    cursor: grabbing;
}

.delete-btn {
    cursor: pointer;
}

.box-content {
    margin-top: 40px;
    font-size: 18px;
    text-align: center;
    line-height: 280px;
    /* 垂直居中 */
    color: #606266;
    user-select: text;
}
</style>
